<template>
  <div class="quote-poster-page">
    <main v-if="product" class="poster-wrapper">
      <div class="poster-scroll">
        <article class="poster-surface">
          <section class="card hero-card">
            <div class="hero-card__info">
              <p class="hero-eyebrow">产品报价</p>
              <h1 class="hero-title" :title="productDisplayName">{{ productDisplayName }}</h1>
              <div class="hero-meta">
                <div class="meta-block">
                  <span class="meta-label">产品编码</span>
                  <span class="meta-value">{{ product.code || '—' }}</span>
                </div>
                <div class="meta-block">
                  <span class="meta-label">产品分类</span>
                  <span class="meta-value">{{ product.category || '—' }}</span>
                </div>
              </div>
            </div>
            <div class="hero-card__price">
              <span class="price-label">最终报价</span>
              <span class="price-value">{{ formatCurrency(finalPrice) }} {{ currency }}</span>
              <small class="price-note">已包含物料、包装及非物料成本</small>
            </div>
            <div class="hero-card__image" v-if="product.mainImageUrl">
              <img :src="product.mainImageUrl" :alt="productDisplayName" />
            </div>
          </section>

          <section class="card section-block">
            <header class="section-header">
              <h2 class="section-title">产品属性</h2>
              <span v-if="loadingEncoding" class="section-sub">属性同步中...</span>
            </header>
            <template v-if="productAttributes.length">
              <dl class="attributes-grid">
                <div
                  v-for="attr in productAttributes"
                  :key="attr.key"
                  class="attribute-item"
                  :class="{ 'attribute-item--encoding': attr.from === 'encoding' }"
                >
                  <dt class="attribute-key">{{ attr.label }}</dt>
                  <dd class="attribute-value">{{ attr.value }}</dd>
                </div>
              </dl>
            </template>
            <p v-else class="empty-hint">暂无可显示的属性</p>
          </section>

          <section v-if="productionBomDisplay.length" class="card section-block">
            <header class="section-header compact-header">
              <h2 class="section-title">物料 BOM</h2>
              <span v-if="bomTotal > 0" class="section-sub">合计 {{ formatCurrency(bomTotal) }} {{ currency }}</span>
            </header>
            <div class="data-table">
              <div class="data-table__head">
                <span class="data-table__cell">物料</span>
                <span class="data-table__cell">名称</span>
                <span class="data-table__cell">单价 × 数量</span>
                <span class="data-table__cell">成本</span>
              </div>
              <div class="data-table__body">
                <div v-for="row in productionBomDisplay" :key="row.id" class="data-table__row">
                  <span class="data-table__cell" :data-label="'物料类型'">{{ row.typeLabel }}</span>
                  <span class="data-table__cell data-table__cell--stack" :data-label="'物料名称'">
                    <span class="cell-primary" :title="row.displayName">{{ row.displayName || '—' }}</span>
                    <span v-if="row.materialCode" class="cell-secondary">{{ row.materialCode }}</span>
                  </span>
                  <span class="data-table__cell" :data-label="'单价 × 数量'">{{ row.quantityDisplay }}</span>
                  <span class="data-table__cell data-table__cell--strong" :data-label="'成本'">{{ formatCurrency(row.lineTotal) }} {{ currency }}</span>
                </div>
              </div>
            </div>
          </section>

          <section class="card section-block" v-if="packages.length">
            <header class="section-header compact-header">
              <h2 class="section-title">包装方式</h2>
              <div class="package-selector-inline">
                <PackageCostSelector
                  v-model="selectedPackageId"
                  :packages="packages"
                  @cost-change="onPackageCostChange"
                  inline
                />
              </div>
            </header>
            <Transition name="bom-slide-fade">
              <div v-if="selectedPackageId && packageBomDisplay.length" class="package-bom-content">
                <div class="data-table">
                  <div class="data-table__head">
                    <span class="data-table__cell">物料</span>
                    <span class="data-table__cell">名称</span>
                    <span class="data-table__cell">单价 × 数量</span>
                    <span class="data-table__cell">成本</span>
                  </div>
                  <div class="data-table__body">
                    <div v-for="row in packageBomDisplay" :key="row.id" class="data-table__row">
                      <span class="data-table__cell" :data-label="'物料类型'">{{ row.typeLabel }}</span>
                      <span class="data-table__cell data-table__cell--stack" :data-label="'物料名称'">
                        <span class="cell-primary" :title="row.displayName">{{ row.displayName || '—' }}</span>
                        <span v-if="row.materialCode" class="cell-secondary">{{ row.materialCode }}</span>
                      </span>
                      <span class="data-table__cell" :data-label="'单价 × 数量'">{{ row.quantityDisplay }}</span>
                      <span class="data-table__cell data-table__cell--strong" :data-label="'成本'">{{ formatCurrency(row.lineTotal) }} {{ currency }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </Transition>
          </section>

          <section v-if="extraFeeList.length" class="card section-block">
            <header class="section-header compact-header">
              <h2 class="section-title">非物料成本</h2>
              <span v-if="extraFeesTotal > 0" class="section-sub">合计 {{ formatCurrency(extraFeesTotal) }} {{ currency }}</span>
            </header>
            <ul class="fee-list">
              <li v-for="fee in extraFeeList" :key="fee.key" class="fee-item">
                <span class="fee-label">{{ fee.label }}</span>
                <span class="fee-value">{{ formatCurrency(fee.amount) }} {{ currency }}</span>
              </li>
            </ul>
          </section>

          <section class="card section-block final-summary">
            <header class="section-header">
              <h2 class="section-title">最终报价汇总</h2>
            </header>
            <div class="summary-grid">
              <div class="summary-line">
                <span>物料成本</span>
                <span>{{ formatCurrency(bomTotal) }} {{ currency }}</span>
              </div>
              <div class="summary-line" v-if="packageCostAmount > 0">
                <span>包装成本</span>
                <span>{{ formatCurrency(packageCostAmount) }} {{ currency }}</span>
              </div>
              <div class="summary-line" v-if="extraFeesTotal > 0">
                <span>非物料成本</span>
                <span>{{ formatCurrency(extraFeesTotal) }} {{ currency }}</span>
              </div>
              <div class="summary-divider"></div>
              <div class="summary-total">
                <span>最终报价</span>
                <span>{{ formatCurrency(finalPrice) }} {{ currency }}</span>
              </div>
            </div>
          </section>
        </article>
      </div>
    </main>

    <section v-else class="page-state">
      <div class="state-card">
        <template v-if="loadingProduct">
          <div class="state-spinner" aria-label="加载中"></div>
          <p class="state-text">正在加载产品数据...</p>
        </template>
        <template v-else-if="productNotFound">
          <p class="state-text">未找到产品信息：<strong>{{ routeCode }}</strong></p>
        </template>
        <template v-else>
          <p class="state-text">暂无产品数据</p>
        </template>
      </div>
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import PackageCostSelector from './components/PackageCostSelector.vue';
import { useUnifiedAttributes } from '../../composables/useUnifiedAttributes';
import { fetchSkuEncodingDetail } from '../../services/sku';
import { searchPackages, PackageItem } from '../../services/package';
import { useSkuStore, BomItemMock, SkuProductBase } from '../../store/sku';

const route = useRoute();
const skuStore = useSkuStore();

const currency = 'CNY';
const skuCode = ref('');
const routeCode = ref('');
const loadingProduct = ref(false);
const productNotFound = ref(false);
const loadingEncoding = ref(false);
const packages = ref<PackageItem[]>([]);

const product = computed<SkuProductBase | undefined>(() =>
  skuCode.value ? skuStore.getProduct(skuCode.value) : undefined
);

const productDisplayName = computed(() => {
  const name = product.value?.name?.trim();
  return name && name.length > 0 ? name : product.value?.code || '—';
});

const bom = computed<BomItemMock[]>(() => (skuCode.value ? skuStore.getBom(skuCode.value) : []));

const harborFee = computed(() => (skuCode.value ? skuStore.getExtraFees(skuCode.value).harbor : 0));
const cuttingFee = computed(() => (skuCode.value ? skuStore.getExtraFees(skuCode.value).cutting : 0));
const laborManufactureFee = computed(() => (skuCode.value ? skuStore.getExtraFees(skuCode.value).labor : 0));
const extraFeesTotal = computed(() => harborFee.value + cuttingFee.value + laborManufactureFee.value);

const packageCost = computed(() =>
  skuCode.value
    ? skuStore.getPackageCost(skuCode.value)
    : { packageId: '', packageName: '', packageCode: '', cost: 0 }
);

const selectedPackageId = ref('');
watch(
  packageCost,
  value => {
    if (!value.packageId && selectedPackageId.value) {
      selectedPackageId.value = '';
    } else if (value.packageId && selectedPackageId.value !== value.packageId) {
      selectedPackageId.value = value.packageId;
    }
  },
  { immediate: true }
);

// 监听 selectedPackageId 的变化，确保与 packageCost 同步
watch(
  selectedPackageId,
  newValue => {
    if (!newValue) {
      // 取消选择时，清空存储的包装成本
      if (skuCode.value) {
        skuStore.setPackageCost(skuCode.value, { packageId: '', packageName: '', packageCode: '', cost: 0 });
      }
    }
  }
);

const packageCostAmount = computed(() =>
  typeof packageCost.value.cost === 'number' && Number.isFinite(packageCost.value.cost)
    ? packageCost.value.cost
    : 0
);

const selectedPackage = computed(() => 
  selectedPackageId.value ? packages.value.find(p => p.id === selectedPackageId.value) : null
);

const encodingDetail = ref<Record<string, any> | null>(null);

const { unified: unifiedAttrs } = useUnifiedAttributes({
  productRef: product as any,
  encodingDetailRef: encodingDetail,
  includeBaseFields: false
});

interface AttributeEntry {
  key: string;
  label: string;
  value: string;
  from: string;
}

const EXCLUDED_ATTRIBUTE_KEYS = new Set(['客户简称', '模具', '品名', '编码', '分类', '产品分类']);

const productAttributes = computed<AttributeEntry[]>(() =>
  unifiedAttrs.value
    .map(attr => ({
      key: attr.key,
      label: attr.key,
      value: attr.value?.toString().trim() || '',
      from: attr.from
    }))
    .filter(entry => entry.value.length > 0)
    .filter(entry => !EXCLUDED_ATTRIBUTE_KEYS.has(entry.label.trim()))
);

interface BomDisplayRow extends BomItemMock {
  displayName: string;
  quantityDisplay: string;
  lineTotal: number;
  typeLabel: string;
}

const typeLabelMap: Record<BomItemMock['type'], string> = {
  production: '生产物料',
  packaging: '包装物料'
};

function buildQuantityAndTotal(row: BomItemMock) {
  const detail = row.feeDetail;
  if (detail) {
    if (detail.mode === 'fixed') {
      return { quantityDisplay: '/', lineTotal: detail.amount || 0 };
    }
    const qty = detail.quantity ?? row.qty;
    const unitPrice = detail.amount || 0;
    return { quantityDisplay: `${unitPrice.toFixed(2)} x ${qty}`, lineTotal: unitPrice * qty };
  }
  const unitCost = row.unitCost || 0;
  const qty = row.qty;
  return { quantityDisplay: `${unitCost.toFixed(2)} x ${qty}`, lineTotal: unitCost * qty };
}

const productionBomDisplay = computed<BomDisplayRow[]>(() =>
  bom.value
    .filter(row => row.type === 'production')
    .map(row => {
      const { quantityDisplay, lineTotal } = buildQuantityAndTotal(row);
      return {
        ...row,
        displayName: row.costName || row.materialName,
        quantityDisplay,
        lineTotal,
        typeLabel: row.category?.trim() || typeLabelMap[row.type] || '—'
      };
    })
);

const packageBomDisplay = computed<BomDisplayRow[]>(() => {
  if (!selectedPackage.value?.bomS || !Array.isArray(selectedPackage.value.bomS)) {
    return [];
  }
  
  return selectedPackage.value.bomS.map((item: any, idx: number) => {
    const b = item.bom || {};
    const qty = item.quantity || 1;
    const feeAmount = b.feeAmount || 0;
    const feeMode = b.feeModel || 'fixed';
    
    let quantityDisplay = '';
    let lineTotal = 0;
    
    if (feeMode === 'fixed') {
      quantityDisplay = '/';
      lineTotal = feeAmount;
    } else {
      quantityDisplay = `${feeAmount.toFixed(2)} x ${qty}`;
      lineTotal = feeAmount * qty;
    }
    
    return {
      id: b.id || `package-bom-${idx}`,
      type: 'packaging' as const,
      seq: idx + 1,
      materialName: b.name || '',
      materialCode: b.invCode || '',
      costName: b.name || '',
      category: b.className || '',
      spec: '',
      qty: qty,
      unit: 'pcs',
      lossFactor: 1,
      unitCost: feeAmount,
      source: '',
      attributes: {},
      feeDetail: {
        mode: feeMode as 'fixed' | 'count',
        amount: feeAmount,
        quantity: qty,
        currency: 'CNY'
      },
      displayName: b.name || '—',
      quantityDisplay,
      lineTotal,
      typeLabel: b.className || '包装物料'
    } as BomDisplayRow;
  });
});

const bomTotal = computed(() => productionBomDisplay.value.reduce((sum, row) => sum + row.lineTotal, 0));

const finalPrice = computed(() => bomTotal.value + extraFeesTotal.value + packageCostAmount.value);

const extraFeeList = computed(() =>
  [
    { key: 'harbor', label: '港杂费', amount: harborFee.value },
    { key: 'cutting', label: '裁切费用', amount: cuttingFee.value },
    { key: 'labor', label: '人工制造费用', amount: laborManufactureFee.value }
  ].filter(item => item.amount > 0)
);

function normalizeEncodingDetail(detail: Record<string, any> | null) {
  if (!detail) return null;
  const baseAttributes = { ...(detail.attributes || detail.dynamicAttributes || {}) };
  const mapped = {
    客户简称: detail.cusShortName,
    模具: detail.mould,
    尺寸: detail.buildingSize || detail.innerSizeMm,
    材质: detail.materialQuality,
    功能: detail.productFun,
    形状: detail.buildingFinishedShape,
    类别: detail.productCategories
  } as Record<string, any>;

  for (const [key, value] of Object.entries(mapped)) {
    if (value !== undefined && value !== null && String(value).trim().length > 0) {
      baseAttributes[key] = value;
    }
  }

  return { ...detail, attributes: baseAttributes };
}

async function loadByCode(code: string) {
  if (!code) {
    skuCode.value = '';
    productNotFound.value = false;
    encodingDetail.value = null;
    selectedPackageId.value = '';
    packages.value = [];
    return;
  }

  skuCode.value = code;
  selectedPackageId.value = '';
  encodingDetail.value = null;
  productNotFound.value = false;

  loadingProduct.value = true;
  await skuStore.loadProductByCode(code);
  loadingProduct.value = false;

  if (!product.value) {
    productNotFound.value = true;
    return;
  }

  // 加载包装列表
  try {
    const res = await searchPackages({ page: 1, pageSize: 100, status: 'enabled' });
    packages.value = res.data?.records || [];
  } catch (error) {
    console.error('加载包装列表失败', error);
    packages.value = [];
  }

  const preset = skuStore.getPackageCost(code);
  selectedPackageId.value = preset.packageId || '';

  loadingEncoding.value = true;
  try {
    const detail = await fetchSkuEncodingDetail(code);
    if (product.value && detail?.materialName && typeof detail.materialName === 'string') {
      const name = detail.materialName.trim();
      if (name.length > 0) {
        product.value.name = name;
      }
    }
    encodingDetail.value = normalizeEncodingDetail(detail);
  } catch (error) {
    console.error('获取编码详情失败', error);
    encodingDetail.value = null;
  } finally {
    loadingEncoding.value = false;
  }
}

function onPackageCostChange(packageInfo: { packageId: string; packageName: string; packageCode: string; cost: number }) {
  if (!skuCode.value) return;
  skuStore.setPackageCost(skuCode.value, packageInfo);
}

function formatCurrency(value: number) {
  return Number.isFinite(value) ? value.toFixed(2) : '0.00';
}

watch(
  () => route.params.code,
  codeParam => {
    if (typeof codeParam === 'string') {
      routeCode.value = codeParam;
      loadByCode(codeParam);
    } else {
      routeCode.value = '';
      loadByCode('');
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.quote-poster-page {
  min-height: 100vh;
  background: radial-gradient(circle at 30% 20%, #e2f1ff 0%, #f5f8fd 45%, #ffffff 100%);
  padding: clamp(1rem, 2vw, 1.4rem) 0 2.4rem;
  display: flex;
  flex-direction: column;
}

.poster-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.poster-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 0 clamp(0.8rem, 4vw, 2.4rem);
}

.poster-scroll::-webkit-scrollbar {
  width: 8px;
}

.poster-scroll::-webkit-scrollbar-thumb {
  background: rgba(100, 116, 139, 0.35);
  border-radius: 6px;
  transition: background 0.2s;
}

.poster-scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(71, 85, 105, 0.6);
}

.poster-surface {
  max-width: 920px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.card {
  background: #ffffff;
  border-radius: 20px;
  border: 1px solid rgba(203, 213, 225, 0.5);
  padding: clamp(1.15rem, 2vw, 1.5rem);
  box-shadow: 0 20px 48px -26px rgba(15, 23, 42, 0.24), 0 8px 16px -8px rgba(15, 23, 42, 0.08);
  transition: box-shadow 0.3s ease;
}

.card:hover {
  box-shadow: 0 24px 60px -24px rgba(15, 23, 42, 0.32), 0 10px 20px -6px rgba(15, 23, 42, 0.12);
}

.hero-card {
  display: grid;
  grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr);
  gap: clamp(1rem, 2.5vw, 1.6rem);
  align-items: stretch;
  background: linear-gradient(135deg, #eef5ff 0%, #fafbff 48%, #f5f8fd 100%);
}

.hero-card__info {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.hero-eyebrow {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #3b82f6;
}

.hero-title {
  margin: 0;
  font-size: clamp(1.95rem, 3.8vw, 2.65rem);
  font-weight: 800;
  color: #0f172a;
  line-height: 1.1;
  letter-spacing: -0.015em;
}

.hero-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.6rem;
}

.meta-block {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.meta-label {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #7c8fa1;
  font-weight: 600;
}

.meta-value {
  font-size: 0.95rem;
  font-weight: 600;
  color: #1a202c;
  word-break: break-word;
}

.hero-card__price {
  border-radius: 18px;
  background: linear-gradient(135deg, #2563eb 0%, #3b82f6 65%, #60a5fa 100%);
  color: #ffffff;
  padding: clamp(1rem, 1.5vw, 1.25rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  box-shadow: 0 20px 40px -20px rgba(37, 99, 235, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.15);
}

.price-label {
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.92;
  font-weight: 600;
}

.price-value {
  font-size: clamp(1.85rem, 3.5vw, 2.35rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
}

.price-note {
  font-size: 0.72rem;
  opacity: 0.88;
  line-height: 1.3;
}

.hero-card__image {
  grid-column: span 2;
  justify-self: flex-end;
  align-self: center;
  max-width: 240px;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid rgba(148, 163, 184, 0.3);
  box-shadow: 0 18px 40px -22px rgba(15, 23, 42, 0.45);
  background: #f5f8fc;
}

.hero-card__image img {
  width: 100%;
  height: auto;
  display: block;
  object-fit: cover;
}

.section-block {
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.compact-header {
  gap: 0.8rem;
  align-items: center;
  flex-wrap: wrap;
}

.section-title {
  margin: 0;
  font-size: 1.22rem;
  font-weight: 700;
  color: #0f172a;
  position: relative;
  padding-left: 0.65rem;
}

.section-title::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  height: 70%;
  border-radius: 999px;
  background: linear-gradient(180deg, #3b82f6 0%, #6366f1 100%);
}

.section-sub {
  font-size: 0.82rem;
  color: #3b82f6;
  font-weight: 600;
}

.section-header .section-sub {
  background: linear-gradient(90deg, #2563eb 0%, #3b82f6 50%, #06b6d4 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.attributes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0.8rem;
}

.attribute-item {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.85rem 0.95rem;
  border-radius: 15px;
  background: linear-gradient(160deg, #ffffff 0%, #f3f7fc 70%);
  border: 1px solid rgba(148, 163, 184, 0.25);
}

.attribute-item--encoding {
  border-color: rgba(37, 99, 235, 0.3);
  background: linear-gradient(160deg, #eff2ff 0%, #ffffff 65%);
}

.attribute-key {
  margin: 0;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #7c8fa1;
  font-weight: 700;
}

.attribute-value {
  margin: 0;
  font-size: 0.93rem;
  font-weight: 600;
  color: #0f172a;
  line-height: 1.35;
  word-break: break-word;
}

.empty-hint {
  margin: 0;
  font-size: 0.88rem;
  color: #a0afc4;
  padding: 0.8rem 0;
}

.data-table {
  border: 1px solid rgba(226, 232, 240, 0.8);
  border-radius: 16px;
  overflow: hidden;
  background: #fafbfc;
}

.data-table__head {
  display: grid;
  grid-template-columns: 1.2fr 2fr 1.2fr 1fr;
  gap: 0.8rem;
  padding: 0.85rem 1rem;
  background: linear-gradient(135deg, #f0f7ff 0%, #eef2ff 100%);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: #5a6f8b;
  align-items: center;
}

.data-table__body {
  display: flex;
  flex-direction: column;
}

.data-table__row {
  display: grid;
  grid-template-columns: 1.2fr 2fr 1.2fr 1fr;
  gap: 0.8rem;
  padding: 0.88rem 1rem;
  border-top: 1px solid rgba(226, 232, 240, 0.5);
  align-items: center;
  transition: background 0.15s ease;
}

.data-table__row:first-child {
  border-top: none;
}

.data-table__row:hover {
  background: rgba(59, 130, 246, 0.04);
}

.data-table__cell {
  font-size: 0.93rem;
  color: #4b5563;
  font-weight: 500;
  display: flex;
  align-items: center;
}

.data-table__cell:nth-child(3) {
  font-weight: 600;
  background: linear-gradient(90deg, transparent 0%, rgba(59, 130, 246, 0.05) 100%);
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  color: #2563eb;
  font-family: 'Courier New', Courier, monospace;
  letter-spacing: 0.02em;
  font-size: 0.96rem;
}

.data-table__cell--stack {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  color: #0f172a;
  justify-content: flex-start;
  align-items: flex-start;
}

.cell-primary {
  font-weight: 600;
  color: #0f172a;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cell-secondary {
  font-size: 0.8rem;
  color: #9ba8b8;
  font-weight: 500;
}

.data-table__cell--strong {
  font-weight: 700;
  color: #1e40af;
  text-align: left;
  justify-content: flex-start;
  background: linear-gradient(90deg, transparent 0%, rgba(30, 64, 175, 0.06) 100%);
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
}

.package-selector-inline {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  justify-content: flex-start;
  min-width: 0;
  flex: 0 1 auto;
}

.package-bom-content {
  margin-top: 1rem;
  padding-top: 0;
  border-top: none;
  animation: slideFadeIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.fee-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.fee-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.95rem;
  color: #4b5563;
}

.fee-label {
  font-weight: 600;
}

.fee-value {
  font-weight: 700;
  color: #1a202c;
}

.fee-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 0.8rem;
  border-top: 1px dashed rgba(148, 163, 184, 0.5);
  font-weight: 700;
  color: #1a202c;
  font-size: 0.98rem;
}

.final-summary {
  background: linear-gradient(135deg, #eef5ff 0%, #fafbff 100%);
}

.summary-grid {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.summary-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.95rem;
  color: #4b5563;
  font-weight: 500;
  padding: 0.5rem 0;
}

.summary-divider {
  height: 1px;
  background: linear-gradient(90deg, rgba(148, 163, 184, 0.1), rgba(148, 163, 184, 0.6), rgba(148, 163, 184, 0.1));
  margin: 0.5rem 0;
}

.summary-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: clamp(1.15rem, 2.2vw, 1.28rem);
  font-weight: 800;
  color: #0f172a;
  padding: 0.6rem 0;
  background: linear-gradient(90deg, transparent 0%, rgba(37, 99, 235, 0.08) 100%);
  padding: 0.8rem 1rem;
  border-radius: 12px;
  border-left: 4px solid #3b82f6;
}

.summary-total span:last-child {
  background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-state {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.state-card {
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(226, 232, 240, 0.7);
  padding: 2rem 2.4rem;
  border-radius: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  box-shadow: 0 20px 40px -24px rgba(15, 23, 42, 0.2);
}

.state-spinner {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid rgba(148, 163, 184, 0.25);
  border-top-color: #3b82f6;
  animation: spin 0.85s linear infinite;
}

.state-text {
  margin: 0;
  font-size: 0.95rem;
  color: #4b5563;
  text-align: center;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes slideFadeIn {
  from {
    opacity: 0;
    transform: translateY(-16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideFadeOut {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-16px);
  }
}

.bom-slide-fade-enter-active {
  animation: slideFadeIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.bom-slide-fade-leave-active {
  animation: slideFadeOut 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}

@media (max-width: 960px) {
  .hero-card {
    grid-template-columns: 1fr;
  }

  .hero-card__price {
    grid-column: span 1;
  }

  .hero-card__image {
    grid-column: span 1;
    justify-self: center;
    max-width: 100%;
  }

  .data-table__head,
  .data-table__row {
    grid-template-columns: 1fr 1.5fr 1fr 0.9fr;
    gap: 0.6rem;
  }

  .section-header {
    flex-direction: column;
    align-items: flex-start;
  }

  .package-selector-inline {
    width: 100%;
    justify-content: flex-start;
  }
}

@media (max-width: 720px) {
  .poster-scroll {
    padding: 0 0.95rem;
  }

  .card {
    padding: 1rem;
    border-radius: 16px;
  }

  .hero-card {
    gap: 1rem;
  }

  .poster-surface {
    gap: 0.95rem;
  }

  .section-title {
    font-size: 1.1rem;
  }

  .data-table__head {
    display: none;
  }

  .data-table__row {
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding: 0.8rem 0.85rem;
  }

  .data-table__cell {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.6rem;
    font-size: 0.9rem;
  }

  .data-table__cell::before {
    content: attr(data-label);
    font-weight: 700;
    color: #7c8fa1;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-size: 0.68rem;
    min-width: 80px;
  }

  .data-table__cell--stack {
    flex-direction: column;
    align-items: flex-start;
    justify-content: space-between;
  }

  .data-table__cell--strong {
    justify-content: space-between;
  }

  .attributes-grid {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  }
}

@media (max-width: 520px) {
  .quote-poster-page {
    padding-top: 0.8rem;
  }

  .poster-scroll {
    padding: 0 0.75rem;
  }

  .hero-title {
    font-size: 1.75rem;
  }

  .price-value {
    font-size: 1.65rem;
  }

  .summary-total {
    font-size: 1.08rem;
  }

  .card {
    padding: 0.9rem;
  }

  .section-title {
    font-size: 1rem;
  }
}
</style>
